from django.shortcuts import render
from django.views import View
from django import http
from django.core.paginator import Paginator, EmptyPage
from django.utils import timezone
from datetime import datetime

from .models import GoodsCategory, SKU, GoodsVisitCount
from contents.utils import get_categories
from.utils import get_breadcrumb
from meiduo_01.utils.response_code import RETCODE

# Create your views here.


class DetailVisitView(View):
    """统计分类商品的访问量，浏览详情页，纪录该产品所在分类被访问的次数"""
    def post(self, req, category_id):
        """收集访问信息"""
        # 接收和校验参数
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return http.HttpResponseForbidden('category_id不存在')

        # 获取当天时间
        t = timezone.localtime()
        # 获取当天的时间字符串
        today_str = '%d-%02d-%02d' % (t.year, t.month, t.day)
        # 将当天的时间字符串，转成时间对象datetime，为了跟date字段的类型匹配 2019-05-11
        # strptime : 字符串转时间对象，strftime 时间对象转字符串
        today_data = datetime.strptime(today_str, '%Y-%m-%d')

        # 统计指定商品的访问量
        # 判断当天指定的商品分类对应的纪录是否存在
        try:
            # counts_day = GoodsVisitCount.objects.get(date=today_data)
            counts_data = GoodsVisitCount.objects.get(date=today_data, category=category)
        except GoodsVisitCount.DoesNotExist:
            # 如果不存在，chuangjian纪录...居然不会创建了
            counts_data = GoodsVisitCount()

        # 此时已经确认有记录，然后完成纪录访问量的逻辑
        counts_data.category = category
        counts_data.date = today_data
        counts_data.count += 1

        # !!!!!! 忘了save
        try:
            counts_data.save()
        except Exception as e:
            return http.HttpResponseServerError('统计失败')

        # 响应结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})


class DetailsView(View):
    """商品详情页"""
    def get(self, req, sku_id):
        """
        提供商品详情页
        :param req:
        :param sku_id:
        :return:
        """
        # 接收和校验参数
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return render(req, '404.html')

        # 查询商品分类
        categories = get_categories()
        # 面包屑导航
        breadcrumb = get_breadcrumb(sku.category)

        # 返回商品详情 # TODO【不太懂】
        # 构建当前商品的规格键
        sku_specs = sku.specs.order_by('spec_id')
        sku_key = []
        for spec in sku_specs:
            sku_key.append(spec.option.id)
        # 获取当前商品的所有SKU
        skus = sku.spu.sku_set.all()
        # 构建不同规格参数（选项）的sku字典
        spec_sku_map = {}
        for s in skus:
            # 获取sku的规格参数
            s_specs = s.specs.order_by('spec_id')
            # 用于形成规格参数-sku字典的键
            key = []
            for spec in s_specs:
                key.append(spec.option.id)
            # 向规格参数-sku字典添加记录
            spec_sku_map[tuple(key)] = s.id
        # 获取当前商品的规格信息
        goods_specs = sku.spu.specs.order_by('id')
        # 若当前sku的规格信息不完整，则不再继续
        if len(sku_key) < len(goods_specs):
            return
        for index, spec in enumerate(goods_specs):
            # 复制当前sku的规格键
            key = sku_key[:]
            # 该规格的选项
            spec_options = spec.options.all()
            for option in spec_options:
                # 在规格参数sku字典中查找符合当前规格的sku
                key[index] = option.id
                option.sku_id = spec_sku_map.get(tuple(key))
            spec.spec_options = spec_options

        # 构造上下文
        context = {
            'categories': categories,
            'breadcrumb': breadcrumb,
            'sku': sku,
            'specs': goods_specs,
        }

        # 返回响应
        return render(req, 'detail.html', context)


class HotsGoodsView(View):
    """获取热销数据"""
    def get(self, req, category_id):
        """
        查询指定分类的SKU信息，而且必须是上架的状态，然后按照销量由高到低排序，最后切片取出前两位
        :param req:
        :param category_id:
        :return:
        """
        # 校验参数category_id的范围，防止11111111111
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            # return http.HttpResponseNotFound()
            return http.HttpResponseForbidden('category_id不存在')
        skus = SKU.objects.filter(category_id=category_id, is_launched=True).order_by('-sales')[:2]

        # 将模型列表转字典列表，构造JSON数据
        hot_skus = []
        for sku in skus:
            sku_dict = {
                # 'default_image_url': sku.default_image_url,
                'default_image_url': sku.default_image.url,  # 取出全路径
                'name': sku.name,
                'price':sku.price,
                # id 没想到要传
                'id': sku.id,
            }
            hot_skus.append(sku_dict)

        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'hot_skus': hot_skus})


class ListView(View):
    """商品列表页"""
    def get(self, req, category_id, page_num):
        """查询并展示商品"""
        # 校验参数category_id的范围，防止11111111111
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            # return http.HttpResponseNotFound()
            return http.HttpResponseForbidden('category_id不存在')
        sort = req.GET.get('sort', 'default')  # 如果没有取到sort，则赋值default

        if sort == 'price':
            sort_field = 'price'
        elif sort == 'hot':
            # sort_field = 'sales'
            sort_field = '-sales'  # 按照销量从高到低
        else:
            sort = 'default'  # 当出现sort== 其他字符时 将sort改成default
            # sort_field = 'create_time'
            sort_field = '-sales'

        # 获取商品分类表
        categories = get_categories()

        # 查询面包屑导航
        breadcrumb = get_breadcrumb(category)

        # 分页和排序查询：category查询sku，一查多，用一方的模型对象.多方关联字段.all/filter()
        # skus = SKU.objects.filter(category=category, is_launched=True)  # 没工作经验的写法（条件查询）
        # skus = SKU.objects.filter(category_id=category_id, is_launched=True)
        # 注意是类名小写加_set（set在这里是集合的意思）# 有工作经验的写法（关联查询）
        # skus = category.sku_set.filter(is_launched=True).order_by(creat_time, price, -sales)

        skus = category.sku_set.filter(is_launched=True).order_by(sort_field)
        # skus = category.sku_set.all()

        # 分页
        # 创建分页器
        # Paginator('要展示的内容'， '每页多少条纪录)
        paginator = Paginator(skus, 5)

        # 取到用户当前要看的那一页【核心数据】 page_num 那一页可能没有数据
        try:
            page_sku = paginator.page(page_num)  # page_num是当前页(传进来的参数)，此句：获取到page_num页中的无条记录
        except EmptyPage:
            return http.HttpResponseNotFound("Empty Page")

        # 获取总页数  !!!!!不熟练
        total_page = paginator.num_pages

        context = {
            'categories': categories,
            'breadcrumb': breadcrumb,
            # 'sku': skus,
            'page_sku': page_sku,
            'total_page': total_page,
            'sort': sort,
            'page_num': page_num,
            'category_id': category_id
        }

        return render(req, 'list.html', context)

